Skip to content

fix(ui): copy selection misaligns on wide (CJK) characters#548

Merged
benvinegar merged 1 commit into
modem-dev:mainfrom
endotakuya:fix/copy-selection-cjk-cells
Jul 17, 2026
Merged

fix(ui): copy selection misaligns on wide (CJK) characters#548
benvinegar merged 1 commit into
modem-dev:mainfrom
endotakuya:fix/copy-selection-cjk-cells

Conversation

@endotakuya

Copy link
Copy Markdown
Contributor

Summary

Mouse-drag copy selection drifted whenever the selection crossed full-width characters (CJK, emoji). Mouse coordinates are terminal cell columns, but the copy path sliced rendered lines with String.prototype.slice, which counts UTF-16 code units. ASCII stays aligned (1 cell = 1 code unit), but each full-width character is 1 code unit and 2 cells, so every one before a selection endpoint shifted the copied text by one position.

  • add cellRangeToCharRange in src/ui/lib/text.ts to convert an inclusive terminal-cell range into code-unit slice bounds, walking grapheme clusters so wide characters and emoji are never split
  • convert cell columns to string indices before every slice in renderCopySelectionText (code-only and decorated paths, drag start and end) and in expandSelectionPoint (double/triple-click word and line selection)
  • fix the file-header copy path too: renderFileHeaderCopyText now measures the gap and clamps by cells, matching DiffFileHeaderRow's cell-based layout for wide-character filenames
  • keep zero-width characters at a selection boundary so invisible characters round-trip through the clipboard
  • add a patch changeset

Repro

Drag-select the prefix export const message = 'こんにちは on this line:

export const message = 'こんにちは'; // greeting

That prefix is 29 UTF-16 code units but 34 terminal cells (five full-width characters, +1 cell each), so slicing by code units overshoots by five cells:

Copied text
Before export const message = 'こんにちは'; //
After export const message = 'こんにちは'

Testing

  • bun run typecheck
  • bun run lint
  • bun run format:check
  • bun run test:theme-contrast
  • bun test
  • bun run test:integration
  • bun run test:tty-smoke

@greptile-apps

greptile-apps Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

PR author is not in the allowed authors list.

@endotakuya
endotakuya force-pushed the fix/copy-selection-cjk-cells branch from 44f07ba to f62e08a Compare July 15, 2026 15:53
@benvinegar
benvinegar merged commit 11747f1 into modem-dev:main Jul 17, 2026
8 checks passed
@benvinegar

Copy link
Copy Markdown
Member

Thanks for the thoughtful fix and thorough coverage! 🙏

This comment was generated by Pi using OpenAI GPT-5.2

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants